import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jayway.jsonpath.JsonPath;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.random.RandomGenerator;
import java.util.stream.Collectors;

public class Handler extends HttpServlet {
    private final Logger lgr = Logger.getLogger(Handler.class.getName());
    private final ObjectMapper mapper = new ObjectMapper();
    private final DbService dbService = new DbService();

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String mytype = request.getParameter("mytype");
        String start = request.getParameter("start");
        String stop = request.getParameter("stop");
        String by = request.getParameter("by");

        if (by == null) {
            throw new RuntimeException("'by' обязательный параментр, необходимо указать параметр  'by'");
        }

        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");

        PrintWriter writer = response.getWriter();
        writer.print(collectToArrayJsonString(dbService.getData(mytype, start, stop, by)));
        writer.flush();
//        response.getOutputStream().print("<b>Hello" + name + ", world. In bold. Name: </b>");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {

        BufferedReader reader = request.getReader();
        int intValueOfChar;
        StringBuilder requestBody = new StringBuilder();
        while ((intValueOfChar = reader.read()) != -1) {
            requestBody.append((char) intValueOfChar);
        }
        lgr.log(Level.INFO, requestBody.toString());

//        response.getWriter().println(requestBody);
        response.getWriter().println(
                saveAndReturnRequest(requestBody.toString())
        );
        // printWriter, возвращаемый методом getWriter, нужно обязательно закрывать
        response.getWriter().close();
    }

    protected String saveAndReturnRequest(String json) throws JsonProcessingException {
//        log.info(json);
        Entity entity = new Entity();
        entity.setOriginal(json);

        String createdString = JsonPath.read(
                json
                , "$.answer.created"
        );
        LocalDateTime created = LocalDateTime.parse(
                createdString, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")
        );
        entity.setCreated(created);

        Map<String, String> map = new HashMap<>();
        LinkedHashMap<String, Object> qId = JsonPath.read(
                json
                , "$.answer.data"
        );

        qId.forEach((s, o) -> {
            List<String> slug = JsonPath.read(
                    o
                    , ".question.slug");

            List<String> text = new ArrayList<>();

            List<Integer> listId = JsonPath.read(o,
                    ".answer_type.id");
            var id = listId.get(0);
            switch (id) {
                case 1, 2 -> text = JsonPath.read(o, ".value");
                case 3 -> text = JsonPath.read(o, ".value[0].text");
                case 34 -> text = getPathString(o);
            }
//            System.out.println(slug.get(0) + "  --  " + text.get(0));
            map.put(slug.get(0), text.get(0));
        });
        LinkedHashMap<String, String> linkedHashMapId = new LinkedHashMap<>();
        LinkedHashMap<String, String> linkedHashMapQuestion = new LinkedHashMap<>();
        Map<String, Integer> keys = new HashMap<>();

        dbService.getLinkedHashMapQuestion().forEach((k, v) -> {
            if (map.containsKey(k)) {
                linkedHashMapId.put(k, map.get(k));
                if (linkedHashMapQuestion.containsKey(v)) {
                    keys.put(v, keys.get(v) + 1);
                    linkedHashMapQuestion.put(v + "_" + keys.get(v), map.get(k));
                } else {
                    linkedHashMapQuestion.put(v, map.get(k));
                    keys.put(v, 1);
                }
            }
        });

        linkedHashMapId.put("created", createdString);
        linkedHashMapQuestion.put("created", createdString);

        String writeMapIdValueAsString = mapper
//                .writerWithDefaultPrettyPrinter()
                .writeValueAsString(linkedHashMapId);

        String writeMapQuestionValueAsString = mapper
//                .writerWithDefaultPrettyPrinter()
                .writeValueAsString(linkedHashMapQuestion);

        lgr.log(Level.INFO, writeMapIdValueAsString);

        entity.setType(map.get("answer_choices_38893275"));
        entity.setJsonId(writeMapIdValueAsString);
        entity.setJsonQuestion(writeMapQuestionValueAsString);
        dbService.insertData(entity);

        return writeMapQuestionValueAsString;
    }

    private String collectToArrayJsonString(List<String> listJsonElements) {
        return listJsonElements
                .stream()
                .collect(Collectors.joining(",", "[", "]"));
    }

    private List<String> getPathString(Object array) {
        List<String> list = JsonPath.read(array, ".value[*].path");
        String collect = String.join(", ", list);
        return List.of(collect);
    }
}